// PaperList.java
import java.util.ArrayList;
import java.util.List;

public class PaperList {
    private final String teacher;
    private final List<Paper> papers; // 不可变列表（通过防御性复制保证）
    private final PaperSelection selections = new PaperSelection();
    private PaperSelectionStrategy strategy = new RandomSelectionStrategy(); // 默认随机策略

    public PaperList(String teacher, List<Paper> papers) {
        this.teacher = teacher;
        this.papers = new ArrayList<>(papers); // 防御性复制
    }

    public void setStrategy(PaperSelectionStrategy strategy) {
        this.strategy = strategy;
    }

    private List<Paper> getUnselectedPapersByType(PaperType type) {
        List<Paper> results = new ArrayList<>();
        for (Paper p : papers) {
            if (!selections.isSelected(p)) {
                if (type == PaperType.Any || matchesType(p, type)) {
                    results.add(p);
                }
            }
        }
        return new ArrayList<>(results); // 防御性复制
    }

    private boolean matchesType(Paper p, PaperType type) {
        String className = p.getClass().getSimpleName();
        return className.equals(type.toString());
    }

    public List<Paper> selectPaperByRandom(Student student) throws NoEnoughPapersException {
        // 前置条件检查
        if (student == null) {
            throw new IllegalArgumentException("学生不能为null");
        }
        if (hasStudentSelected(student)) {
            throw new IllegalArgumentException("学生" + student.getName() + "已选择过论文");
        }

        List<Paper> availablePapers = getUnselectedPapersByType(student.getPreferredPaperType());
        int required = student.getPreferredQuantity();

        if (availablePapers.size() < required) {
            throw new NoEnoughPapersException(
                "学生" + student.getName() + "希望选" + required + "篇，但目前只有" + availablePapers.size() + "篇可选"
            );
        }

        List<Paper> selected = strategy.select(availablePapers, required);
        for (Paper p : selected) {
            selections.addSelection(student, p);
        }
        return selected;
    }

    private boolean hasStudentSelected(Student student) {
        return selections.getSelections().values().contains(student);
    }

    public PaperSelection getSelectionResult() {
        return selections;
    }
}